home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / mega src / Source / cat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-17  |  7.1 KB  |  328 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     cat.c
  4.     
  5.     Copyright (c) 1993,1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #define    CAT_BUF_SIZE    2048
  16.  
  17. #include <script.h>
  18. #include <string.h>
  19.  
  20. #include "nshc.h"
  21.  
  22. #include "arg_utl.proto.h"
  23. #include "fss_utl.proto.h"
  24. #include "fss_utl2.proto.h"
  25. #include "nshc_utl.proto.h"
  26. #include "str_utl.proto.h"
  27.  
  28. // data definition - this struct is the root of all data
  29.  
  30. typedef enum { copy_none, copy_data, copy_rsrc } c_state;
  31.  
  32. typedef struct {
  33.  
  34.     int        by_file;        // 1 if files are listed, 0 if stdin
  35.  
  36.     int        got_fss;        // 0 if FSSpec calls are not available
  37.  
  38.     int        arg;            // position in arg list
  39.     
  40.     short    fref;            // file ref. number, 0 if no file open
  41.  
  42. } t_cat_data;
  43.  
  44. typedef    t_cat_data    **CDataH;
  45.  
  46. /* ======================================== */
  47.  
  48. // prototypes - utility
  49.  
  50. void cat_bad( t_nshc_parms *nshc_parms, int code );
  51. void cat_bad_file( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg );
  52. void cat_good( t_nshc_parms *nshc_parms );
  53.  
  54. // prototypes - file copy routines
  55.  
  56. void cat_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData );
  57. void cat_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData );
  58.  
  59. // prototypes - console copy routines
  60.  
  61. void cat_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  62.  
  63. // prototypes - state machine
  64.  
  65. void cat_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  );
  66. void cat_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  67. void cat_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  68.  
  69. /* ======================================== */
  70.  
  71. // utility routines
  72.  
  73. /* ======================================== */
  74.  
  75. void cat_bad(  t_nshc_parms *nshc_parms, int code )
  76. {
  77.     nshc_parms->action = nsh_stop;
  78.     nshc_parms->result = code;
  79. }
  80.  
  81. void cat_bad_file(  t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg )
  82. {
  83.     nshc_calls->NSH_putStr_err("\pcat: File access error (");
  84.     nshc_calls->NSH_putStr_err(msg);
  85.     nshc_calls->NSH_putStr_err("\p)\r");
  86.  
  87.     nshc_parms->action = nsh_stop;
  88.     nshc_parms->result = NSHC_ERR_GENERAL;
  89. }
  90.  
  91. void cat_good(  t_nshc_parms *nshc_parms )
  92. {
  93.     nshc_parms->action = nsh_stop;
  94.     nshc_parms->result = 0;
  95. }
  96.  
  97. /* ======================================== */
  98.  
  99. // file access routines
  100.  
  101. /* ======================================== */
  102.  
  103. void cat_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData )
  104. {
  105.     int        result;
  106.     long    dirID;
  107.     Boolean    isDir;
  108.     FSSpec    fss;
  109.     
  110.     (**hData).fref = 0;
  111.  
  112.     // =====> convert path to fsspec
  113.     
  114.     result = arg_to_fss( nshc_parms, nshc_calls, (**hData).arg, &fss );
  115.  
  116.     (**hData).arg++;
  117.     
  118.     if (result) {
  119.         cat_bad( nshc_parms, result );
  120.         return;
  121.         }
  122.     
  123.     result = fss_to_DirID( &fss, &dirID, &isDir );
  124.         
  125.     if (( result == noErr) && isDir) {
  126.         nshc_calls->NSH_putStr_err("\pcat: Skiping directory = ");
  127.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  128.         nshc_calls->NSH_putchar('\r');
  129.         return;
  130.         }
  131.             
  132.     if ( result == fnfErr ) {
  133.         nshc_calls->NSH_putStr_err("\pcat: File not found = ");
  134.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  135.         nshc_calls->NSH_putchar('\r');
  136.         return;
  137.         }
  138.             
  139.     if (!result)
  140.         result = fss_OpenDF((**hData).got_fss, &fss, fsRdPerm, &(**hData).fref);
  141.     
  142.     if ( result ) {
  143.         cat_bad_file( nshc_parms, nshc_calls, (StringPtr)fss.name );
  144.         return;
  145.         }
  146. }
  147.  
  148. /* ======================================== */
  149.  
  150. void cat_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_cat_data **hData )
  151. {
  152.     int        close;
  153.     int        temp;
  154.     int        result;
  155.     long    bcount;
  156.     char    buf[CAT_BUF_SIZE+1];
  157.     
  158.     result = close = 0;
  159.     
  160.     // =====> copy the data fork
  161.     
  162.     bcount = CAT_BUF_SIZE;
  163.     result = FSRead( (**hData).fref, &bcount, &buf );
  164.     
  165.     if (( result == noErr ) || ( result == eofErr )) {
  166.     
  167.         if (result == eofErr) {
  168.             close = 1;
  169.             result = 0;
  170.             }
  171.         
  172.         if (bcount) {
  173.             buf[bcount] = '\0';
  174.             nshc_calls->NSH_puts( buf );
  175.             }
  176.         
  177.         }
  178.     else
  179.         cat_bad_file( nshc_parms, nshc_calls, "\pread data" );
  180.     
  181.     // =====> close the input file
  182.     
  183.     if (close) {
  184.  
  185.         if ( (**hData).fref ) {
  186.             if ( temp = FSClose( (**hData).fref ) )
  187.                 result = temp;
  188.             (**hData).fref = 0;
  189.             }
  190.             
  191.         if (result)
  192.             cat_bad_file( nshc_parms, nshc_calls, "\pclose file" );
  193.                 
  194.         }
  195. }
  196.  
  197. /* ======================================== */
  198.  
  199. // console access routines
  200.  
  201. /* ======================================== */
  202.  
  203. void cat_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  204. {
  205.     long    bcount;
  206.     char    buf[LINE_MAX];
  207.     char    c;
  208.     int        i;
  209.     int        temp;
  210.     
  211.     bcount = nshc_calls->NSH_gets( buf, LINE_MAX );
  212.     
  213.     if (!bcount) return;            // wait for characters
  214.     
  215.     nshc_calls->NSH_puts( buf );    // display the line
  216.     
  217.     if ( bcount == -1 )                // end of input, set-up for exit
  218.         cat_good( nshc_parms );
  219. }
  220.  
  221. /* ======================================== */
  222.  
  223. // state machine - core routines
  224.  
  225. /* ======================================== */
  226.  
  227. void cat_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  )
  228. {
  229.     CDataH    hData;    // handle to hold our data
  230.     
  231.     nshc_parms->action = nsh_continue;
  232.  
  233.     hData = (CDataH)NewHandleClear(sizeof(t_cat_data));
  234.     
  235.     if (hData) {
  236.         (**hData).by_file = nshc_parms->argc > 1;    // if we have args, do file i/o
  237.         (**hData).arg = 1;                            // start at the arg = 1 position
  238.         (**hData).got_fss = fss_test();                // test if we can use FSSpec calls
  239.         nshc_parms->data = (Handle)hData;
  240.         }
  241.     else {
  242.         nshc_calls->NSH_putStr_err( "\pcat: Could not allocate storage.\r" );
  243.         cat_bad( nshc_parms, NSHC_ERR_MEMORY );
  244.         }
  245. }
  246.  
  247. /* ======================================== */
  248.  
  249. void cat_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  250. {
  251.     CDataH    hData;
  252.  
  253.     if (hData = (CDataH)nshc_parms->data) {
  254.  
  255.         if ( (**hData).by_file ) {
  256.         
  257.             // if we are not in the middle of a file, open one
  258.  
  259.             if ( !(**hData).fref )
  260.                 cat_open( nshc_parms, nshc_calls, hData );
  261.  
  262.             // read and write some of the open file
  263.  
  264.             if ( (**hData).fref )
  265.                 cat_read_write( nshc_parms, nshc_calls, hData );
  266.  
  267.             // and see if we are done
  268.  
  269.             if ( !(**hData).fref && ( (**hData).arg >= nshc_parms->argc ) )
  270.                 cat_good( nshc_parms );
  271.                 
  272.             }
  273.         else
  274.             cat_console( nshc_parms, nshc_calls );
  275.  
  276.         }
  277. }
  278.  
  279. /* ======================================== */
  280.  
  281. void cat_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  282. {
  283.     short    fRef;
  284.     CDataH    hData;
  285.     int        temp;
  286.     int        result;
  287.     
  288.     result = 0;
  289.     
  290.     if (hData = (CDataH)nshc_parms->data) {
  291.     
  292.         if ( (**hData).fref ) {
  293.             if ( temp = FSClose( (**hData).fref ) )
  294.                 result = temp;
  295.             (**hData).fref = 0;
  296.             }
  297.             
  298.         DisposeHandle(nshc_parms->data);
  299.         }
  300.         
  301.     if (result)
  302.         cat_bad_file( nshc_parms, nshc_calls, "\pclosing files" );
  303.         
  304.     nshc_parms->action = nsh_idle;
  305. }
  306.  
  307. /* ======================================== */
  308.  
  309. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  310. {
  311.     
  312.     if (nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION )) return;
  313.     
  314.     switch (nshc_parms->action) {
  315.         case nsh_start:
  316.             cat_start(nshc_parms, nshc_calls);
  317.             break;
  318.         case nsh_continue:
  319.             cat_continue(nshc_parms, nshc_calls);
  320.             break;
  321.         case nsh_stop:
  322.             cat_stop(nshc_parms, nshc_calls);
  323.             break;
  324.         }
  325. }
  326.  
  327. /* ======================================== */
  328.